/*
 * Copyright (c) 2025 [ByteDance Ltd. and/or its affiliates.] and/or its affiliates
 * SPDX-License-Identifier: LGPL v2.1+
*/
#include "ffmpeg_io_cryptor.h"
#include "FFmpegIOCryptor.h"
#include "FFmpegXORIOEncryptor.h"
#include "FFErrorCodeDef.h"
#include "FFAny.h"
#include "FFMathUtils.h"

#ifdef __cplusplus
extern "C"
{
#endif

void* createIODeCrptorContext(AVFormatContext *formatCtx, const char *url, const AVDictionary *options, const FFCrptorParams crptorParams) {
    FFmpegIOCryptor* deCryptor = NULL;
    auto cryptorType = te_get_cryptor_type(url);
    if (cryptorType != TECryptorType_None) {
        deCryptor = te_create_ffmpeg_io_decryptor(cryptorType);
        if (!deCryptor) {
            return NULL;
        }
        std::map<std::string, FFAny> params;
        params.insert(std::pair<std::string, FFAny>(kFFmpegIOCryptorParam_Step, (uint32_t)crptorParams.step));
        params.insert(std::pair<std::string, FFAny>(kFFmpegIOCryptorParam_Length, (uint32_t)crptorParams.lenght));
        params.insert(std::pair<std::string, FFAny>(kFFmpegIOCryptorParam_Key, (uint8_t)crptorParams.key));
        auto ret = deCryptor->prepare(url, formatCtx, options, &params);
        if (ret < 0) {
            if (deCryptor) {
                delete deCryptor;
                deCryptor = NULL;
            }
            return NULL;
        }
    }
    return deCryptor;
}
    
void clearFormatContext(void* deCryptor) {
    if (deCryptor) {
        FFmpegIOCryptor* cryptor = (FFmpegIOCryptor*)deCryptor;
        cryptor->clearFormatContext();
    }
}

void* createIOEnCrptorContext(AVFormatContext *formatCtx, const char *url, const AVDictionary *options, const FFCrptorParams crptorParams) {
    std::map<std::string, FFAny> params;
    FFmpegIOEncryptor* enCryptor = te_create_ffmpeg_io_encryptor(TECryptorType_XOR);
    params.insert(std::pair<std::string, FFAny>(kFFmpegIOCryptorParam_Step, (uint32_t)crptorParams.step));
    params.insert(std::pair<std::string, FFAny>(kFFmpegIOCryptorParam_Length, (uint32_t)crptorParams.lenght));
    params.insert(std::pair<std::string, FFAny>(kFFmpegIOCryptorParam_Key, (uint8_t)crptorParams.key));
    if (!enCryptor) {
        return NULL;
    }
    auto ret = enCryptor->prepare(url, formatCtx, NULL, &params);
    if (ret < 0) {
        if (enCryptor) {
            delete enCryptor;
            enCryptor = NULL;
        }
        return NULL;
    }
    return enCryptor;
}
    
int writeBdveTag(void* enCryptor, int writeParam) {
    int ret = -1;
    if (enCryptor) {
        FFmpegIOEncryptor* cryptor = static_cast<FFmpegIOEncryptor *>(enCryptor);
        ret = cryptor->writeBdveTag(writeParam == 1 ? true : false);
    }
    return ret;
}

void destoryIOCryptor(void* ioCrptor) {
    if (ioCrptor) {
        FFmpegIOEncryptor* cryptor = (FFmpegIOEncryptor*)ioCrptor;
        if (cryptor) {
            delete cryptor;
            cryptor = NULL;
        }
    }
}

void destroyIODecryptor(void* ioCrptor) {
    if (ioCrptor) {
        FFmpegIOCryptor *cryptor = (FFmpegIOCryptor *)ioCrptor;
        if (cryptor) {
            delete cryptor;
            cryptor = NULL;
        }
    }
}

#ifdef __cplusplus
}
#endif
